﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITAP.ContourBuilder.Components;

using System.Drawing;
using ITAP.ContourBuilder.Components.Dimensions;
using ITAP.Core.Modelling;

namespace ITAP.ContourBuilder.Manipulation
{
    public class CommandSelectComponents : Command
    {
        private List<Type> acceptedTypesToSelect = null;
        public CommandSelectComponents(ContourControl control)
            : base(control)
        {
        }

        public CommandSelectComponents(ContourControl control, Type[] acceptedTypesToSelect)
            : this(control)
        {
            this.acceptedTypesToSelect = new List<Type>(acceptedTypesToSelect);
        }

        private Point prevMouseDownLocation = new Point(int.MaxValue, int.MaxValue);
        private bool isMouseUpPressed = false;

        public override void ObtainPeripheryState(GlobalPeripheryState state)
        {
            base.ObtainPeripheryState(state);

            if (state.MouseState.MouseMode == MouseMode.Down && state.MouseState.State.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (state.MouseState.State.Location == prevMouseDownLocation && !isMouseUpPressed)
                    return;

                isMouseUpPressed = false;

                prevMouseDownLocation = state.MouseState.State.Location;

                ModelPoint point = this.ScreenPointToModelPoint(state.MouseState.State.Location);
                IEnumerable<IContourComponent> allComponents = control.ContourContainer.GetAllInnerComponents();

                foreach (Type type in acceptedTypesToSelect)
                {

                    foreach (IContourComponent component in allComponents)
                    {

                        if (!(component is Dimension))
                        {

                            if (!this.acceptedTypesToSelect.Contains(component.GetType()))
                                continue;

                            if (component.GetType() != type)
                                continue;
                        }
                        bool canSelectByPoint = component.CanSelectByPoint(point);
                        // Когда выбирается невыбранная точка, надо её селектить, при этом если нажат Shift, оставлять другие точки выбранными.
                        if (canSelectByPoint && !component.Selected)
                        {
                            if (state.KeyboardState.KeyState.KeyCode != System.Windows.Forms.Keys.ShiftKey)
                                control.ContourContainer.DeselectAll();

                            if (control.ContourContainer.SelectedComponentsStack.Count != 0)
                                if (component.GetType() != control.ContourContainer.SelectedComponentsStack[0].GetType())
                                    continue;

                            control.ContourContainer.SelectedComponentsStack.Add(component);
                            component.SelectByPoint(point);
                        }
                        // Когда выбирается уже выбранная точка, то надо её селектить/деселектить по Shift.
                        else if (canSelectByPoint && component.Selected)
                        {
                            if (state.KeyboardState.KeyState.KeyCode == System.Windows.Forms.Keys.ShiftKey)
                            {
                                component.Selected = false;
                                control.ContourContainer.SelectedComponentsStack.Remove(component);
                            }
                        }
                    }
                }
                bool isOneOrMoreSelected = false;
                foreach (IContourComponent component in allComponents)
                    if (component.CanSelectByPoint(point))
                        isOneOrMoreSelected = true;

                if (!isOneOrMoreSelected)
                    control.ContourContainer.DeselectAll();

            }
            else if (state.MouseState.MouseMode == MouseMode.Up)
                isMouseUpPressed = true;

            this.control.Invalidate();
        }

        public override object Clone()
        {
            CommandSelectComponents clone = (CommandSelectComponents)base.Clone();
            clone.acceptedTypesToSelect = new List<Type>(this.acceptedTypesToSelect);
            return clone;
        }
    }
}
